import {onUnmounted, ref} from "vue";
import {KeyboardEventConfig, KeyboardEventMode} from "@/ts/keyboard";

class Key{

    // 键盘名
    name:string=''

    // 键盘key值
    keyCode:number=-1

    // 键盘key名
    code:string=''

    // 键盘大小
    size:number=1


    shiftName:string=''

    constructor(name:string,keyCode:number,code?:string,shiftName?:string,size?:number) {
        this.name=name
        this.keyCode=keyCode
        typeof code === "string" ? this.code = code : this.code=name
        typeof shiftName === 'string'?this.shiftName=shiftName:''
        typeof size === "number" ? this.size = size : 1
    }
}
export default function (){
    const activeIndex = ref(-1)
    const activeKeyName=ref("")
    const inputLock=ref(true)
    const defaultKeyboardEventConfig:KeyboardEventConfig={
        mode: KeyboardEventMode.ALL,
        duration: 0,
        exclude: [],
        include: [],
        callback:(): void =>{}
    }
    const kbConfig=ref<KeyboardEventConfig>()

    const keyList=[

        new Key('`', 192, 'Backquote', '~', 2),
        new Key('1', 49, 'Digit1', '!'),
        new Key('2', 50, 'Digit2', '@'),
        new Key('3', 51, 'Digit3', '#'),
        new Key('4', 52, 'Digit4', '$'),
        new Key('5', 53, 'Digit5', '%'),
        new Key('6', 54, 'Digit6', '^'),
        new Key('7', 55, 'Digit7', '&'),
        new Key('8', 56, 'Digit8', '*'),
        new Key('9', 57, 'Digit9', '('),
        new Key('0', 48, 'Digit0', ')'),
        new Key('-', 189, 'Minus', '_'),
        new Key('=', 187, 'Equal', '+'),
        new Key('Back', 8, 'Backspace', '', 4),
        new Key('Tab', 9, 'Tab', '', 3),
        // index:15
        new Key('Q', 81, 'KeyQ'),
        new Key('W', 87, 'KeyW'),
        new Key('E', 69, 'KeyE'),
        new Key('R', 82, 'KeyR'),
        new Key('T', 84, 'KeyT'),
        new Key('Y', 89, 'KeyY'),
        new Key('U', 85, 'KeyU'),
        new Key('I', 73, 'KeyI'),
        new Key('O', 79, 'KeyO'),
        new Key('P', 80, 'KeyP'),
        // index:25
        new Key('[', 219, 'BracketLeft', '{'),
        new Key(']', 221, 'BracketRight', '}'),
        new Key('\\', 220, 'Backslash', '|', 3),
        new Key('CapsLk', 20, 'CapsLock', '', 4),
        // index:29
        new Key('A', 65, 'KeyA'),
        new Key('S', 83, 'KeyS'),
        new Key('D', 68, 'KeyD'),
        new Key('F', 70, 'KeyF'),
        new Key('G', 71, 'KeyG'),
        new Key('H', 72, 'KeyH'),
        new Key('J', 74, 'KeyJ'),
        new Key('K', 75, 'KeyK'),
        new Key('L', 76, 'KeyL'),
        // index:38
        new Key(';', 186, 'Semicolon', ':'),
        new Key('\'', 222, 'Quote', '"'),
        new Key('Enter', 13, 'Enter', '', 4),
        new Key('Shift', 16, 'ShiftLeft', '', 5),
        // index:42
        new Key('Z', 90, 'KeyZ'),
        new Key('X', 88, 'KeyX'),
        new Key('C', 67, 'KeyC'),
        new Key('V', 86, 'KeyV'),
        new Key('B', 66, 'KeyB'),
        new Key('N', 78, 'KeyN'),
        new Key('M', 77, 'KeyM'),
        // 49
        new Key(',', 188, 'Comma', '<'),
        new Key('.', 190, 'Period', '>'),
        new Key('/', 191, 'Slash', '?'),
        new Key('Shift', 16, 'ShiftRight', '', 5),
        new Key('Ctrl', 17, 'ControlLeft', '', 3),
        new Key('Win', 91, 'MetaLeft', '', 3),
        new Key('Alt', 18, 'AltLeft', '', 3),
        new Key('Space', 32, 'Space', '', 12),
        new Key('Alt', 18, 'AltRight', '', 3),
        new Key('Fn', -1, '', '', 2),
        new Key('Sp', -1, '', '', 2),
        new Key('Ctrl', 17, 'ControlRight', '', 2),

    ]

    const simpleKeyList:Array<number>=[1,2,3,4,5,6,7,8,9,10,15,16,17,18,19,20,21,22,23,24,29,30,31,32,33,34,35,36,37,42,43,44,45,46,47,48,56]

    // 白名单
    let whiteKeyList:Array<number>


    function updateActiveIndex(e:KeyboardEvent){
        // 判断锁
        if(!inputLock.value){
            return
        }
        const keyCode = e.keyCode
        const code = e.code
        // 从keyList中找到该按键对象
        const index:number = keyList.findIndex((key) => {
            return key.code === code && key.keyCode === keyCode
        })

        // 白名单包含即可改变
        if (index >= 0  && whiteKeyList.includes(index)) {
            // 上锁
            inputLock.value=false
            // 改索引值
            activeIndex.value = index
            // 改字符名值
            activeKeyName.value=getKeyName(index)

            // @ts-ignore
            const callback=kbConfig.value.callback
            if (callback){
                callback(activeIndex.value,activeKeyName.value,keyList)
            }

            // 放锁
            setTimeout(()=>{
                inputLock.value=true
            },kbConfig.value?.duration || 0)
            e.preventDefault()
        }
    }

    function keydownEvent(e:KeyboardEvent){
        updateActiveIndex(e)

    }
    function keyupEvent(){

        activeIndex.value = -1

    }
    
    /**
     *  键盘事件启动
     *
     * */
    function start(config?:KeyboardEventConfig){
        console.log('[keyboard event] start')
        setConfig(config || defaultKeyboardEventConfig)
        document.removeEventListener("keydown",keydownEvent)
        document.removeEventListener("keyup",keyupEvent)
        // 键盘按下,根据code查找键（keyCode辅助查找）
        document.addEventListener("keydown", keydownEvent)
        // 键盘弹起
        document.addEventListener("keyup", keyupEvent)
        
        // 移除监听事件
        onUnmounted(()=>{
            console.log('[keyboard event] end')
            document.removeEventListener("keydown",keydownEvent)
            document.removeEventListener("keyup",keyupEvent)
        })
    }
    /**
     *  mode: simple 包含数字和26个字母  /   all 全部按键
     *  include: 额外允许的，优先级 > exclude
     *  exclude: 排除的
     *  duration: 两次按键之间的间隔时间，单位ms
     *
     * */
    function setConfig(config:KeyboardEventConfig){
        // 初始化
        whiteKeyList=[]
        // 缓存
        kbConfig.value=config
        // 根据模式配置键盘白名单
        const mode = kbConfig.value?.mode
        if( mode === KeyboardEventMode.EMPTY){
            // 什么都不加
        }
        else if( mode ===  KeyboardEventMode.SIMPLE){
            // 白名单加入a-z
            whiteKeyList.push(...simpleKeyList)
        }else if( mode ===  KeyboardEventMode.ALL ){
            // 白名单加入所有
            keyList.forEach((item,index)=>{
                whiteKeyList.push(index)
            })
        }

        // 根据exclude剔除
        config.exclude?.forEach(item=>{
            const index = getIndex(item);
            const indexOfIndex = whiteKeyList.indexOf(index);
            // 此索引存在白名单中，删除
            if(indexOfIndex !== -1){
                whiteKeyList.splice(indexOfIndex,1)
            }
        })
        // 根据include增加白名单
        config.include?.forEach((item)=>{
            // 获取对应索引
            const index = getIndex(item);
            // 不包含则加入
            if(!whiteKeyList.includes(index)){
                whiteKeyList.push(index)
            }
        })
    }
    // 根据索引找键名
    function getKeyName(index:number){
        return keyList[index].name
    }

    function getKey(index:number){
        return keyList[index]
    }
    // 根据键名找索引 a/A -> 20
    function getIndex(name:string){
        return keyList.findIndex((item)=>item.name.toLowerCase() === name.toLowerCase())
    }


    return{
        // 激活键索引
        activeIndex,
        activeKeyName,
        // 所有键list
        keyList,
        // 通过索引获取键名,例如20 -> y
        getKeyName,
        // 通过索引获取键对象
        getKey,
        // 根据字符获取键索引
        getIndex,
        // 设置键盘配置
        setConfig,
        // 启动监听方法
        start
    }

}
